package com.common.core.utils;

import com.common.core.WyyMusicConstant;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.jsoup.HttpStatusException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import sun.misc.BASE64Encoder;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.downloader.Downloader;
import us.codecraft.webmagic.downloader.HttpClientDownloader;
import us.codecraft.webmagic.proxy.Proxy;
import us.codecraft.webmagic.proxy.SimpleProxyProvider;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Pattern;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * Author : wangyu
 * Date: 2018-03-05
 * Time: 16:03
 */
public class WyyMusicUtils {

    public static Downloader getDownloader(){
        final String ip = "forward.xdaili.cn";//这里以正式服务器ip地址为准
        final int port = 80;//这里以正式服务器端口地址为准
        //以下订单号，secret参数 须自行改动
        HttpClientDownloader httpClientDownloader = new HttpClientDownloader();
        httpClientDownloader.setProxyProvider(SimpleProxyProvider.from(new Proxy(ip,port)));
        return httpClientDownloader;
    }

    public static Site createSite(){
        int timestamp = (int) (new Date().getTime()/1000);
        final String authHeader = WyyMusicUtils.
                authHeader("ZF2018390920AiLeGP",
                        "be0e91583a4242dc930f8b06f053719f", timestamp);

        //以下订单号，secret参数 须自行改动
        Site site = Site.me()
                .setDomain(WyyMusicConstant.BASE_URL)
                .setSleepTime(30000)
                .setRetryTimes(30)
                .setCharset("utf-8")
                .setTimeOut(30000)
                .setUserAgent(WyyMusicUtils.randomUserAgent())
                .addHeader("Proxy-Authorization", authHeader)
                ;
        return site;
    }

    /**
     * 把long 转换成 日期 再转换成String类型
     */
    public static String transferLongToDate(String dateFormat, Long millSec) {
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        Date date = new Date(millSec);
        return sdf.format(date);
    }

    public static void main(String[] args) {
//        String s = crawlAjaxUrl("2107922801", 10000,WyyMusicConstant.SONG_MENU);
//        System.err.println("爬取到的评论数据:"+s);

        String url = "http://music.163.com/user/home?id=350982013";
        String p = "http://music\\.163\\.com/user/home\\?id=\\d+";

        boolean matches = Pattern.matches(p, url);
        System.err.println(matches);

    }


    //判断是否是全数字
    public static boolean regexNumber(String numStr){
        String pattern = "^\\d+$";
        boolean isMatch = Pattern.matches(pattern, numStr);
        return isMatch;
    }

    //获取代理连接池
    public static Proxy[] getProxys(){
        String[] ips = WyyMusicConstant.ips;
        Proxy[] proxies = new Proxy[ips.length];
        for(int i=0;i<ips.length;i++){
            String ipAndPort = ips[i];
            String[] split = ipAndPort.split(":");
            Proxy proxy = new Proxy(split[0].trim(), Integer.valueOf(split[1].trim()));
            proxies[i] = proxy;
        }
        return proxies;
    }

    /**
     * 随机获取一个浏览器代理人
     * @return
     */
    public static String randomUserAgent(){
        Random random = new Random();
        String[] agents = WyyMusicConstant.agents;
        int i = random.nextInt(agents.length);
        return agents[i];
    }


    public static java.net.Proxy getProxy(){

        HttpHost proxy = new HttpHost("", 0);
        RequestConfig config = RequestConfig.custom().setProxy(proxy).build();

        return null;
    }

    /**
     *
     * @param id 歌曲或者歌单ID
     * @param offset 偏移量
     * @param cmtType 评论类型
     * @return
     */
    public static String crawlAjaxUrl(String id, int offset, String cmtType,String proxyFlag) {
        try {
            Thread.sleep(5000l);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        CloseableHttpClient httpclient = HttpClients.createDefault();
        if("代理".equals(proxyFlag)){
            final String ip = "forward.xdaili.cn";//这里以正式服务器ip地址为准
            final int port = 80;//这里以正式服务器端口地址为准

            //设置代理IP、端口、协议（请分别替换）
            HttpHost proxy = new HttpHost(ip, port);

            //把代理设置到请求配置
            RequestConfig defaultRequestConfig = RequestConfig.custom()
                    .setProxy(proxy)

                    .build();

            //实例化CloseableHttpClient对象
             httpclient = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig).build();


        }

        CloseableHttpResponse response = null;
        String first_param = "{rid:\"\", offset:\"offset_param\", total:\"true\", limit:\""+WyyMusicConstant.CMT_LIMIT+"\", csrf_token:\"\"}";
        first_param = first_param.replace("offset_param", offset + "");
        try {
            // 参数加密
            // 16位随机字符串，直接FFF
            // String secKey = new BigInteger(100, new SecureRandom()).toString(32).substring(0, 16);
            String secKey = "FFFFFFFFFFFFFFFF";
            // 两遍ASE加密
            String encText = WyyMusicUtils.aesEncrypt(aesEncrypt(first_param, "0CoJUm6Qyw8W8jud"), secKey);
            //
            String encSecKey = rsaEncrypt();

            HttpPost httpPost = new HttpPost();
            httpPost.addHeader("User-Agent", randomUserAgent());
            if("代理".equals(proxyFlag)){
                int timestamp = (int) (new Date().getTime()/1000);
                final String authHeader = WyyMusicUtils.
                        authHeader("ZF2018390920AiLeGP",
                                "be0e91583a4242dc930f8b06f053719f", timestamp);
                httpPost.addHeader("Proxy-Authorization", authHeader);
            }

            //组装referer连接,让爬虫跟真实
            String referer = "";
            String uri = "";
            if(WyyMusicConstant.SONG_MENU.equals(cmtType)){
                referer = "http://music.163.com/playlist?id="+id;
                uri = "http://music.163.com/weapi/v1/resource/comments/A_PL_0_"+id+"?csrf_token=";
            }else if(WyyMusicConstant.SONG.equals(cmtType)){
                uri = "http://music.163.com/weapi/v1/resource/comments/R_SO_4_" + id + "/?csrf_token=";
                referer = "http://music.163.com/song?id="+id;
            }
            httpPost.addHeader("Referer", referer);//设置来源
            httpPost.setURI(new URI(uri));//设置URI访问资源

            List<NameValuePair> ls = new ArrayList<NameValuePair>();
            ls.add(new BasicNameValuePair("params", encText));
            ls.add(new BasicNameValuePair("encSecKey", encSecKey));
            UrlEncodedFormEntity paramEntity = new UrlEncodedFormEntity(ls, "utf-8");
            httpPost.setEntity(paramEntity);

            response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();

            if (entity != null) {
                return EntityUtils.toString(entity, "utf-8");
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return "";
    }

    /**
     * ASE-128-CBC加密模式可以需要16位
     *
     * @param src 加密内容
     * @param key 密钥
     * @return
     */
    public static String aesEncrypt(String src, String key) throws Exception {
        String encodingFormat = "UTF-8";
        String iv = "0102030405060708";

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] raw = key.getBytes();
        SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
        // 使用CBC模式，需要一个向量vi，增加加密算法强度
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        byte[] encrypted = cipher.doFinal(src.getBytes(encodingFormat));
        return new BASE64Encoder().encode(encrypted);

    }

    public static String rsaEncrypt() {
        String secKey = "257348aecb5e556c066de214e531faadd1c55d814f9be95fd06d6bff9f4c7a41f831f6394d5a3fd2e3881736d94a02ca919d952872e7d0a50ebfa1769a7a62d512f5f1ca21aec60bc3819a9c3ffca5eca9a0dba6d6f7249b06f5965ecfff3695b54e1c28f3f624750ed39e7de08fc8493242e26dbc4484a01c76f739e135637c";
        return secKey;
    }

    public static String parseMillisecone(long millisecond) {
        String time = null;
        try {
            long yushu_day = millisecond % (1000 * 60 * 60 * 24);
            long yushu_hour = (millisecond % (1000 * 60 * 60 * 24))
                    % (1000 * 60 * 60);
            long yushu_minute = millisecond % (1000 * 60 * 60 * 24)
                    % (1000 * 60 * 60) % (1000 * 60);
            @SuppressWarnings("unused")
            long yushu_second = millisecond % (1000 * 60 * 60 * 24)
                    % (1000 * 60 * 60) % (1000 * 60) % 1000;
            if (yushu_day == 0) {
                return (millisecond / (1000 * 60 * 60 * 24)) + "天";
            } else {
                if (yushu_hour == 0) {
                    return (millisecond / (1000 * 60 * 60 * 24)) + "天"
                            + (yushu_day / (1000 * 60 * 60)) + "时";
                } else {
                    if (yushu_minute == 0) {
                        return (millisecond / (1000 * 60 * 60 * 24)) + "天"
                                + (yushu_day / (1000 * 60 * 60)) + "时"
                                + (yushu_hour / (1000 * 60)) + "分";
                    } else {
                        return (millisecond / (1000 * 60 * 60 * 24)) + "天"
                                + (yushu_day / (1000 * 60 * 60)) + "时"
                                + (yushu_hour / (1000 * 60)) + "分"
                                + (yushu_minute / 1000) + "秒";

                    }

                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return time;
    }

    /*
     * 将时间戳转换为时间
     */
    public static String stampToDate(long s) {
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long lt = s;
        Date date = new Date(lt);
        res = simpleDateFormat.format(date);
        return res;
    }

    /**
     * 将emoji表情替换成*
     *
     * @param source
     * @return 过滤后的字符串
     */
    public static String filterEmoji(String source) {
        if (StringUtils.isNotBlank(source)) {
            return source.replaceAll("[\\ud800\\udc00-\\udbff\\udfff\\ud800-\\udfff]", "*");
        } else {
            return source;
        }
    }

    public static String authHeader(String orderno, String secret, int timestamp){
        //拼装签名字符串
        String planText = String.format("orderno=%s,secret=%s,timestamp=%d", orderno, secret, timestamp);

        //计算签名
        String sign = org.apache.commons.codec.digest.DigestUtils.md5Hex(planText).toUpperCase();

        //拼装请求头Proxy-Authorization的值
        String authHeader = String.format("sign=%s&orderno=%s&timestamp=%d", sign, orderno, timestamp);
        return authHeader;
    }
}
